home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / access / index / istrat.c < prev   
Encoding:
C/C++ Source or Header  |  1992-08-27  |  18.1 KB  |  703 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    istrat.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    index scan strategy manipulation code and 
  7.  *    index strategy manipulation operator code.
  8.  *
  9.  *   INTERFACE ROUTINES
  10.  *    StrategyMapGetScanKeyEntry
  11.  *    IndexStrategyGetStrategyMap
  12.  *    AttributeNumberGetIndexStrategySize
  13.  *    StrategyOperatorIsValid
  14.  *    StrategyTermIsValid
  15.  *    StrategyExpressionIsValid
  16.  *    StrategyEvaluationIsValid
  17.  *    RelationGetStrategy
  18.  *    RelationInvokeStrategy
  19.  *    IndexSupportInitialize
  20.  *    
  21.  *   IDENTIFICATION
  22.  *    $Header: /private/postgres/src/access/index/RCS/istrat.c,v 1.8 1992/03/04 22:13:52 mer Exp $
  23.  * ----------------------------------------------------------------
  24.  */
  25.  
  26. #include "tmp/postgres.h"
  27.  
  28. RcsId("$Header: /private/postgres/src/access/index/RCS/istrat.c,v 1.8 1992/03/04 22:13:52 mer Exp $");
  29.  
  30. #include "access/att.h"
  31. #include "access/attnum.h"
  32. #include "access/heapam.h"
  33. #include "access/istrat.h"
  34. #include "access/isop.h"
  35. #include "access/itup.h"    /* for MaxIndexAttributeNumber */
  36. #include "access/skey.h"
  37. #include "access/tqual.h"    /* for NowTimeQual */
  38.  
  39. #include "utils/log.h"
  40. #include "utils/rel.h"
  41.  
  42. #include "catalog/catname.h"
  43. #include "catalog/pg_amop.h"
  44. #include "catalog/pg_amproc.h"
  45. #include "catalog/pg_index.h"
  46. #include "catalog/pg_proc.h"
  47.  
  48. /*
  49.  * OperatorRelationFillScanKeyEntry --
  50.  *    Fills the scan key entry for an OPERATOR object.
  51.  */
  52. extern
  53. void
  54. OperatorRelationFillScanKeyEntry ARGS((
  55.     Relation    operatorRelation,
  56.     ObjectId    operatorObjectId,
  57.     ScanKeyEntry    entry
  58. ));
  59.  
  60. /* ----------------------------------------------------------------
  61.  *               misc strategy support routines
  62.  * ----------------------------------------------------------------
  63.  */
  64.  
  65. /* 
  66.  *    StrategyNumberIsValid
  67.  *    StrategyNumberIsInBounds
  68.  *    StrategyMapIsValid
  69.  *    StrategyTransformMapIsValid
  70.  *    IndexStrategyIsValid
  71.  *
  72.  *        ... are now macros in istrat.h -cim 4/27/91
  73.  */
  74.  
  75. /* ----------------
  76.  *    StrategyMapGetScanKeyEntry
  77.  * ----------------
  78.  */
  79. ScanKeyEntry
  80. StrategyMapGetScanKeyEntry(map, strategyNumber)
  81.     StrategyMap        map;
  82.     StrategyNumber    strategyNumber;
  83. {
  84.     Assert(StrategyMapIsValid(map));
  85.     Assert(StrategyNumberIsValid(strategyNumber));
  86.     return (&map->entry[strategyNumber - 1]);
  87. }
  88.  
  89. /* ----------------
  90.  *    IndexStrategyGetStrategyMap
  91.  * ----------------
  92.  */
  93. StrategyMap
  94. IndexStrategyGetStrategyMap(indexStrategy, maxStrategyNum, attrNum)
  95.     IndexStrategy    indexStrategy;
  96.     StrategyNumber    maxStrategyNum;
  97.     AttributeNumber    attrNum;
  98. {
  99.     Assert(IndexStrategyIsValid(indexStrategy));
  100.     Assert(StrategyNumberIsValid(maxStrategyNum));
  101.     Assert(AttributeNumberIsValid(attrNum));
  102.  
  103.     maxStrategyNum = AMStrategies(maxStrategyNum);    /* XXX */
  104.     return
  105.     &indexStrategy->strategyMapData[maxStrategyNum * (attrNum - 1)];
  106. }
  107.  
  108. /* ----------------
  109.  *    AttributeNumberGetIndexStrategySize
  110.  * ----------------
  111.  */
  112. Size
  113. AttributeNumberGetIndexStrategySize(maxAttributeNumber, maxStrategyNumber)
  114.     AttributeNumber    maxAttributeNumber;
  115.     StrategyNumber    maxStrategyNumber;
  116. {
  117.     maxStrategyNumber = AMStrategies(maxStrategyNumber);    /* XXX */
  118.     return
  119.     maxAttributeNumber * maxStrategyNumber * sizeof (ScanKeyData);
  120. }
  121.  
  122. /* 
  123.  * StrategyTransformMapIsValid is now a macro in istrat.h -cim 4/27/91
  124.  */
  125.  
  126. /* ----------------
  127.  *    StrategyOperatorIsValid
  128.  * ----------------
  129.  */
  130. bool
  131. StrategyOperatorIsValid(operator, maxStrategy)
  132.     StrategyOperator    operator;
  133.     StrategyNumber    maxStrategy;
  134. {
  135.     return (bool)
  136.     (PointerIsValid(operator) &&
  137.      StrategyNumberIsInBounds(operator->strategy, maxStrategy) &&
  138.      !(operator->flags & ~(NegateResult | CommuteArguments)));
  139. }
  140.  
  141. /* ----------------
  142.  *    StrategyTermIsValid
  143.  * ----------------
  144.  */
  145. bool
  146. StrategyTermIsValid(term, maxStrategy)
  147.     StrategyTerm    term;
  148.     StrategyNumber    maxStrategy;
  149. {
  150.     Index    index;
  151.  
  152.     if (! PointerIsValid(term) || term->degree == 0)
  153.     return false;
  154.  
  155.     for (index = 0; index < term->degree; index += 1) {
  156.     if (! StrategyOperatorIsValid(&term->operatorData[index],
  157.                       maxStrategy)) {
  158.  
  159.         return false;
  160.     }
  161.     }
  162.  
  163.     return true;
  164. }
  165.  
  166. /* ----------------
  167.  *    StrategyExpressionIsValid
  168.  * ----------------
  169.  */
  170. bool
  171. StrategyExpressionIsValid(expression, maxStrategy)
  172.     StrategyExpression    expression;
  173.     StrategyNumber        maxStrategy;
  174. {
  175.     StrategyTerm    *termP;
  176.  
  177.     if (!PointerIsValid(expression))
  178.     return true;
  179.  
  180.     if (!StrategyTermIsValid(expression->term[0], maxStrategy))
  181.     return false;
  182.  
  183.     termP = &expression->term[1];
  184.     while (StrategyTermIsValid(*termP, maxStrategy))
  185.     termP += 1;
  186.  
  187.     return (bool)
  188.     (! PointerIsValid(*termP));
  189. }
  190.  
  191. /* ----------------
  192.  *    StrategyEvaluationIsValid
  193.  * ----------------
  194.  */
  195. bool
  196. StrategyEvaluationIsValid(evaluation)
  197.     StrategyEvaluation    evaluation;
  198. {
  199.     Index    index;
  200.  
  201.     if (! PointerIsValid(evaluation) ||
  202.     ! StrategyNumberIsValid(evaluation->maxStrategy) ||
  203.     ! StrategyTransformMapIsValid(evaluation->negateTransform) ||
  204.     ! StrategyTransformMapIsValid(evaluation->commuteTransform) ||
  205.     ! StrategyTransformMapIsValid(evaluation->negateCommuteTransform)) {
  206.  
  207.     return false;
  208.     }
  209.  
  210.     for (index = 0; index < evaluation->maxStrategy; index += 1) {
  211.     if (! StrategyExpressionIsValid(evaluation->expression[index],
  212.                     evaluation->maxStrategy)) {
  213.  
  214.         return false;
  215.     }
  216.     }
  217.     return true;
  218. }
  219.  
  220. /* ----------------
  221.  *    StrategyTermEvaluate
  222.  * ----------------
  223.  */
  224. static
  225. bool
  226. StrategyTermEvaluate(term, map, left, right)
  227.     StrategyTerm    term;
  228.     StrategyMap        map;
  229.     Datum        left;
  230.     Datum        right;
  231. {
  232.     Index        index;
  233.     bool        result;
  234.     StrategyOperator    operator;
  235.     ScanKeyEntry    entry;
  236.  
  237.     for (index = 0, operator = &term->operatorData[0];
  238.      index < term->degree; index += 1, operator += 1) {
  239.  
  240.     entry = &map->entry[operator->strategy - 1];
  241.  
  242.     Assert(RegProcedureIsValid(entry->procedure));
  243.  
  244.     switch (operator->flags ^ entry->flags) {
  245.     case 0x0:
  246.         result = (bool) (*(entry->func)) (left, right);
  247.         break;
  248.         
  249.     case NegateResult:
  250.         result = (bool) !(*(entry->func)) (left, right);
  251.         break;
  252.         
  253.     case CommuteArguments:
  254.         result = (bool) (*(entry->func)) (right, left);
  255.         break;
  256.         
  257.     case NegateResult | CommuteArguments:
  258.         result = (bool) !(*(entry->func)) (right, left);
  259.         break;
  260.  
  261.     default:
  262.         elog(FATAL, "StrategyTermEvaluate: impossible case %d",
  263.          operator->flags ^ entry->flags);
  264.     }
  265.  
  266.     if (!result)
  267.         return result;
  268.     }
  269.     
  270.     return result;
  271. }
  272.  
  273.  
  274. /* ----------------
  275.  *    RelationGetStrategy
  276.  * ----------------
  277.  */
  278. StrategyNumber
  279. RelationGetStrategy(relation, attributeNumber, evaluation, procedure)
  280.     Relation        relation;
  281.     AttributeNumber    attributeNumber;
  282.     StrategyEvaluation    evaluation;
  283.     RegProcedure    procedure;
  284. {
  285.     StrategyNumber    strategy;
  286.     StrategyMap        strategyMap;
  287.     ScanKeyEntry    entry;
  288.     Index        index;
  289.     AttributeNumber     numattrs;
  290.  
  291.     Assert(RelationIsValid(relation));
  292.     numattrs = RelationGetNumberOfAttributes(relation);
  293.  
  294.     Assert(relation->rd_rel->relkind == 'i');    /* XXX use accessor */
  295.     Assert(AttributeNumberIsValid(attributeNumber));
  296.     Assert(OffsetIsInBounds(attributeNumber, 1, 1 + numattrs) );
  297.  
  298.     Assert(StrategyEvaluationIsValid(evaluation));
  299.     Assert(RegProcedureIsValid(procedure));
  300.  
  301.     strategyMap =
  302.     IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation),
  303.                     evaluation->maxStrategy,
  304.                     attributeNumber);
  305.  
  306.     /* get a strategy number for the procedure ignoring flags for now */
  307.     for (index = 0; index < evaluation->maxStrategy; index += 1) {
  308.     if (strategyMap->entry[index].procedure == procedure) {
  309.         break;
  310.     }
  311.     }
  312.  
  313.     if (index == evaluation->maxStrategy)
  314.     return InvalidStrategy;
  315.  
  316.     strategy = 1 + index;
  317.     entry = StrategyMapGetScanKeyEntry(strategyMap, strategy);
  318.  
  319.     Assert(!(entry->flags & ~(NegateResult | CommuteArguments)));
  320.  
  321.     switch (entry->flags & (NegateResult | CommuteArguments)) {
  322.     case 0x0:
  323.     return strategy;
  324.  
  325.     case NegateResult:
  326.     strategy = evaluation->negateTransform->strategy[strategy - 1];
  327.     break;
  328.  
  329.     case CommuteArguments:
  330.     strategy = evaluation->commuteTransform->strategy[strategy - 1];
  331.     break;
  332.  
  333.     case NegateResult | CommuteArguments:
  334.     strategy = evaluation->negateCommuteTransform->strategy[strategy - 1];
  335.     break;
  336.  
  337.     default:
  338.     elog(FATAL, "RelationGetStrategy: impossible case %d", entry->flags);
  339.     }
  340.  
  341.  
  342.     if (! StrategyNumberIsInBounds(strategy, evaluation->maxStrategy)) {
  343.     if (! StrategyNumberIsValid(strategy)) {
  344.         elog(WARN, "RelationGetStrategy: corrupted evaluation");
  345.     }
  346.     }
  347.  
  348.     return strategy;
  349. }
  350.  
  351. /* ----------------
  352.  *    RelationInvokeStrategy
  353.  * ----------------
  354.  */
  355. bool        /* XXX someday, this may return Datum */
  356. RelationInvokeStrategy(relation, evaluation, attributeNumber,
  357.                strategy, left, right)
  358.  
  359.     Relation        relation;
  360.     StrategyEvaluation    evaluation;
  361.     AttributeNumber    attributeNumber;
  362.     StrategyNumber    strategy;
  363.     Datum        left;
  364.     Datum        right;
  365. {
  366.     StrategyNumber    newStrategy;
  367.     StrategyMap        strategyMap;
  368.     ScanKeyEntry    entry;
  369.     StrategyTermData    termData;
  370.     AttributeNumber     numattrs;
  371.  
  372.     Assert(RelationIsValid(relation));
  373.     Assert(relation->rd_rel->relkind == 'i');    /* XXX use accessor */
  374.     numattrs = RelationGetNumberOfAttributes(relation);
  375.     
  376.     Assert(StrategyEvaluationIsValid(evaluation));
  377.     Assert(AttributeNumberIsValid(attributeNumber));
  378.     Assert(OffsetIsInBounds(attributeNumber, 1, 1 + numattrs));
  379.     Assert(StrategyNumberIsInBounds(strategy, evaluation->maxStrategy));
  380.  
  381.     termData.degree = 1;
  382.  
  383.     strategyMap =
  384.     IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation),
  385.                     evaluation->maxStrategy,
  386.                     attributeNumber);
  387.  
  388.     entry = StrategyMapGetScanKeyEntry(strategyMap, strategy);
  389.  
  390.     if (RegProcedureIsValid(entry->procedure)) {
  391.     termData.operatorData[0].strategy = strategy;
  392.     termData.operatorData[0].flags = 0x0;
  393.  
  394.     return
  395.         StrategyTermEvaluate(&termData, strategyMap, left, right);
  396.     }
  397.  
  398.  
  399.     newStrategy = evaluation->negateTransform->strategy[strategy - 1];
  400.     if (newStrategy != strategy && StrategyNumberIsValid(newStrategy)) {
  401.     
  402.     entry = StrategyMapGetScanKeyEntry(strategyMap, newStrategy);
  403.  
  404.     if (RegProcedureIsValid(entry->procedure)) {
  405.         termData.operatorData[0].strategy = newStrategy;
  406.         termData.operatorData[0].flags = NegateResult;
  407.  
  408.         return
  409.         StrategyTermEvaluate(&termData, strategyMap, left, right);
  410.     }
  411.     }
  412.  
  413.     newStrategy = evaluation->commuteTransform->strategy[strategy - 1];
  414.     if (newStrategy != strategy && StrategyNumberIsValid(newStrategy)) {
  415.     
  416.     entry = StrategyMapGetScanKeyEntry(strategyMap, newStrategy);
  417.  
  418.     if (RegProcedureIsValid(entry->procedure)) {
  419.         termData.operatorData[0].strategy = newStrategy;
  420.         termData.operatorData[0].flags = CommuteArguments;
  421.  
  422.         return
  423.         StrategyTermEvaluate(&termData, strategyMap, left, right);
  424.     }
  425.     }
  426.  
  427.     newStrategy = evaluation->negateCommuteTransform->strategy[strategy - 1];
  428.     if (newStrategy != strategy && StrategyNumberIsValid(newStrategy)) {
  429.     
  430.     entry = StrategyMapGetScanKeyEntry(strategyMap, newStrategy);
  431.  
  432.     if (RegProcedureIsValid(entry->procedure)) {
  433.         termData.operatorData[0].strategy = newStrategy;
  434.         termData.operatorData[0].flags = NegateResult | CommuteArguments;
  435.  
  436.         return
  437.         StrategyTermEvaluate(&termData, strategyMap, left, right);
  438.     }
  439.     }
  440.  
  441.     if (PointerIsValid(evaluation->expression[strategy - 1])) {
  442.     StrategyTerm        *termP;
  443.  
  444.     termP = &evaluation->expression[strategy - 1]->term[0];
  445.     while (PointerIsValid(*termP)) {
  446.         Index    index;
  447.  
  448.         for (index = 0; index < (*termP)->degree; index += 1) {
  449.         entry = StrategyMapGetScanKeyEntry(strategyMap,
  450.                    (*termP)->operatorData[index].strategy);
  451.  
  452.         if (! RegProcedureIsValid(entry->procedure)) {
  453.             break;
  454.         }
  455.         }
  456.  
  457.         if (index == (*termP)->degree) {
  458.         return
  459.             StrategyTermEvaluate(*termP, strategyMap, left, right);
  460.         }
  461.  
  462.         termP += 1;
  463.     }
  464.     }
  465.  
  466.     elog(WARN, "RelationInvokeStrategy: cannot evaluate strategy %d",
  467.      strategy);
  468.     /* NOTREACHED */
  469. }
  470.  
  471. /* ----------------
  472.  *    OperatorRelationFillScanKeyEntry
  473.  * ----------------
  474.  */
  475. static
  476. void
  477. OperatorRelationFillScanKeyEntry(operatorRelation, operatorObjectId, entry)
  478.     Relation        operatorRelation;
  479.     ObjectId        operatorObjectId;
  480.     ScanKeyEntry    entry;
  481. {
  482.     HeapScanDesc    scan;
  483.     ScanKeyData        scanKeyData;
  484.     HeapTuple        tuple;
  485.  
  486.     ScanKeyEntryInitialize(&scanKeyData.data[0], 0, 
  487.                ObjectIdAttributeNumber,
  488.                ObjectIdEqualRegProcedure,
  489.                ObjectIdGetDatum(operatorObjectId));
  490.  
  491.     scan = heap_beginscan(operatorRelation, false, NowTimeQual,
  492.               1, &scanKeyData);
  493.  
  494.     tuple = heap_getnext(scan, false, (Buffer *)NULL);
  495.     if (! HeapTupleIsValid(tuple)) {
  496.     elog(WARN, "OperatorObjectIdFillScanKeyEntry: unknown operator %lu",
  497.          (uint32) operatorObjectId);
  498.     }
  499.  
  500.     entry->flags = 0;
  501.     entry->procedure = ((OperatorTupleForm) HeapTupleGetForm(tuple))->oprcode;
  502.     fmgr_info(entry->procedure, &entry->func, &entry->nargs);
  503.  
  504.     if (! RegProcedureIsValid(entry->procedure)) {
  505.     elog(WARN,
  506.          "OperatorObjectIdFillScanKeyEntry: no procedure for operator %lu",
  507.          (uint32) operatorObjectId);
  508.     }
  509.  
  510.     heap_endscan(scan);
  511. }
  512.  
  513.  
  514. /* ----------------
  515.  *    IndexSupportInitialize
  516.  * ----------------
  517.  */
  518. void
  519. IndexSupportInitialize(indexStrategy, indexSupport,
  520.             indexObjectId, accessMethodObjectId,
  521.             maxStrategyNumber, maxSupportNumber,
  522.             maxAttributeNumber)
  523.  
  524.     IndexStrategy    indexStrategy;
  525.     RegProcedure    *indexSupport;
  526.     ObjectId        indexObjectId;
  527.     ObjectId        accessMethodObjectId;
  528.     StrategyNumber    maxStrategyNumber;
  529.     StrategyNumber    maxSupportNumber;
  530.     AttributeNumber    maxAttributeNumber;
  531. {
  532.     Relation        relation;
  533.     Relation        operatorRelation;
  534.     HeapScanDesc    scan;
  535.     HeapTuple        tuple;
  536.     ScanKeyEntryData    entry[2];
  537.     StrategyMap        map;
  538.     AttributeNumber    attributeNumber;
  539.     AttributeOffset    attributeIndex;
  540.     ObjectId        operatorClassObjectId[ MaxIndexAttributeNumber ];
  541.  
  542.     maxStrategyNumber = AMStrategies(maxStrategyNumber);
  543.  
  544.     ScanKeyEntryInitialize(&entry[0], 0, IndexRelationIdAttributeNumber,
  545.                            ObjectIdEqualRegProcedure, 
  546.                            ObjectIdGetDatum(indexObjectId));
  547.  
  548.     relation = heap_openr(IndexRelationName);
  549.     scan = heap_beginscan(relation, false, NowTimeQual, 1, (ScanKey)entry);
  550.     tuple = heap_getnext(scan, false, (Buffer *)NULL);
  551.     if (! HeapTupleIsValid(tuple))
  552.     elog(WARN, "IndexSupportInitialize: corrupted catalogs");
  553.  
  554.     /*
  555.      * XXX note that the following assumes the INDEX tuple is well formed and
  556.      * that the key[] and class[] are 0 terminated.
  557.      */
  558.     for (attributeIndex=0; attributeIndex<maxAttributeNumber; attributeIndex++)
  559.     {
  560.     IndexTupleForm    iform;
  561.  
  562.     iform = (IndexTupleForm) HeapTupleGetForm(tuple);
  563.  
  564.     if (!ObjectIdIsValid(iform->indkey[attributeIndex])) {
  565.         if (attributeIndex == 0) {
  566.         elog(WARN, "IndexSupportInitialize: no pg_index tuple");
  567.         }
  568.         break;
  569.     }
  570.  
  571.     operatorClassObjectId[attributeIndex]
  572.         = iform->indclass[attributeIndex];
  573.     }
  574.  
  575.     heap_endscan(scan);
  576.     heap_close(relation);
  577.  
  578.     /* if support routines exist for this access method, load them */
  579.     if (maxSupportNumber > 0) {
  580.  
  581.     ScanKeyEntryInitialize(&entry[0], 0, Anum_pg_amproc_amid,
  582.                            ObjectIdEqualRegProcedure,
  583.                            ObjectIdGetDatum(accessMethodObjectId));
  584.  
  585.     ScanKeyEntryInitialize(&entry[1], 0, Anum_pg_amproc_amopclaid,
  586.                            ObjectIdEqualRegProcedure, 0);
  587.  
  588.     relation = heap_openr(Name_pg_amproc);
  589.  
  590.     for (attributeNumber = maxAttributeNumber; attributeNumber > 0;
  591.          attributeNumber--) {
  592.  
  593.         int16        support;
  594.         Form_pg_amproc    form;
  595.         RegProcedure    *loc;
  596.  
  597.         loc = &indexSupport[((attributeNumber - 1) * maxSupportNumber)];
  598.  
  599.         for (support = maxSupportNumber; --support >= 0; ) {
  600.         loc[support] = InvalidObjectId;
  601.         }
  602.  
  603.         entry[1].argument =
  604.         ObjectIdGetDatum(operatorClassObjectId[attributeNumber - 1]);
  605.  
  606.         scan = heap_beginscan(relation, false, NowTimeQual, 2,
  607.                   (ScanKey) entry);
  608.  
  609.         while (tuple = heap_getnext(scan, false, (Buffer *)NULL),
  610.            HeapTupleIsValid(tuple)) {
  611.  
  612.         form = (Form_pg_amproc) HeapTupleGetForm(tuple);
  613.         loc[(form->amprocnum - 1)] = form->amproc;
  614.         }
  615.  
  616.         heap_endscan(scan);
  617.     }
  618.     heap_close(relation);
  619.     }
  620.  
  621.     ScanKeyEntryInitialize(&entry[0], 0, 
  622.                AccessMethodOperatorAccessMethodIdAttributeNumber,
  623.                            ObjectIdEqualRegProcedure,
  624.                            ObjectIdGetDatum(accessMethodObjectId));
  625.  
  626.     ScanKeyEntryInitialize(&entry[1], 0, 
  627.                AccessMethodOperatorOperatorClassIdAttributeNumber,
  628.                            ObjectIdEqualRegProcedure, 0);
  629.  
  630.     relation = heap_openr(AccessMethodOperatorRelationName);
  631.     operatorRelation = heap_openr(OperatorRelationName);
  632.  
  633.     for (attributeNumber = maxAttributeNumber; attributeNumber > 0;
  634.      attributeNumber--) {
  635.  
  636.     StrategyNumber    strategy;
  637.  
  638.     entry[1].argument =
  639.         ObjectIdGetDatum(operatorClassObjectId[attributeNumber - 1]);
  640.  
  641.     map = IndexStrategyGetStrategyMap(indexStrategy,
  642.                       maxStrategyNumber,
  643.                       attributeNumber);
  644.  
  645.     for (strategy = 1; strategy <= maxStrategyNumber; strategy++)
  646.         ScanKeyEntrySetIllegal(StrategyMapGetScanKeyEntry(map, strategy));
  647.  
  648.     scan = heap_beginscan(relation, false, NowTimeQual, 2, (ScanKey)entry);
  649.  
  650.     while (tuple = heap_getnext(scan, false, (Buffer *)NULL),
  651.         HeapTupleIsValid(tuple)) {
  652.         AccessMethodOperatorTupleForm form;
  653.  
  654.         form = (AccessMethodOperatorTupleForm) HeapTupleGetForm(tuple);
  655.  
  656.         OperatorRelationFillScanKeyEntry(operatorRelation,
  657.                          form->amopoprid,
  658.                   StrategyMapGetScanKeyEntry(map, form->amopstrategy));
  659.     }
  660.  
  661.     heap_endscan(scan);
  662.     }
  663.  
  664.     heap_close(operatorRelation);
  665.     heap_close(relation);
  666. }
  667.  
  668. /* ----------------
  669.  *    IndexStrategyDisplay
  670.  * ----------------
  671.  */
  672. #ifdef    ISTRATDEBUG
  673. int
  674. IndexStrategyDisplay(indexStrategy, numberOfStrategies, numberOfAttributes)
  675.     IndexStrategy    indexStrategy;
  676.     StrategyNumber    numberOfStrategies;
  677.     AttributeNumber    numberOfAttributes;
  678. {
  679.     StrategyMap    strategyMap;
  680.     AttributeNumber    attributeNumber;
  681.     StrategyNumber    strategyNumber;
  682.  
  683.     for (attributeNumber = 1; attributeNumber <= numberOfAttributes;
  684.      attributeNumber += 1) {
  685.  
  686.     strategyMap = IndexStrategyGetStrategyMap(indexStrategy,
  687.                           numberOfStrategies,
  688.                           attributeNumber);
  689.  
  690.     for (strategyNumber = 1;
  691.          strategyNumber <= AMStrategies(numberOfStrategies);
  692.          strategyNumber += 1) {
  693.  
  694.         printf(":att %d\t:str %d\t:opr 0x%x(%d)\n",
  695.            attributeNumber, strategyNumber,
  696.            strategyMap->entry[strategyNumber - 1].procedure,
  697.            strategyMap->entry[strategyNumber - 1].procedure);
  698.     }
  699.     }
  700. }
  701. #endif    /* defined(ISTRATDEBUG) */
  702.  
  703.